package com.xiaobias;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.*;

public class Server {

    private int port;

    public int getPort() {
        return port;
    }

    // 各线程的引用
    // acceptor thread
    private Acceptor acceptor;
    // pollerIO threads
    private Set<PollerIO> ioThreads;
    // business thread
    private ExecutorService buExecutor;

    // status flag
    public volatile boolean stopped = false;

    public void init() {
        // todo read conf
        this.port = 9999;
        // prepare io thread
        int ioThreadNum = Math.max(4, Runtime.getRuntime().availableProcessors());
        ioThreads = new HashSet<PollerIO>(ioThreadNum);
        for (int i = 0; i < ioThreadNum; i++) {
            PollerIO pollerIO = new PollerIO("poller" + i, this);
            ioThreads.add(pollerIO);
        }
        // prepare acceptor thread
        try {
            this.acceptor = new Acceptor("acceptor", this, this.ioThreads);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void start() {
        // start buExecutor
        this.buExecutor = new ThreadPoolExecutor(
                200,
                500,
                60,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(10000)
        );
        // start io threads
        this.ioThreads.forEach(PollerIO::start);
        // start acceptor thread
        this.acceptor.start();
    }

    public void shutdown() {
        this.stopped = true;
        this.buExecutor.shutdown();
    }

    public static void main(String[] args) {
        CountDownLatch countDownLatch = new CountDownLatch(1);
        Server server = new Server();
        server.init();
        server.start();
        // stop ?
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            server.shutdown();
            countDownLatch.countDown();
        }));
        try {
            countDownLatch.await();
            System.out.println("server 退出");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void addBusTask(BuTask buTask) {
        this.buExecutor.execute(buTask);
    }
}
